package org.fhawk.tinyspring.util;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by tuo on 9/5/2016.
 */
public class AnnotationUtil {

    private AnnotationUtil() {
    }

    /**
     * 查询类是否有某一个注解
     *
     * @param clazz      类
     * @param annotation 注解
     * @return 该类是否有指定注解
     */
    public static boolean isAnnotationPresent(Class<?> clazz, Class<? extends Annotation> annotation) {
        if (clazz.isAnnotationPresent(annotation)) {
            return true;
        }
        //进行递归查询，处理组合注解
        for (Annotation ann : filterMetaAnnotation(clazz.getDeclaredAnnotations())) {
            Class<? extends Annotation> aClass = ann.annotationType();
            if (isAnnotationPresent(aClass, annotation)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 查询字段是否有某一个注解
     *
     * @param field      属性
     * @param annotation 指定注解
     * @return 是否有直接注解
     */
    public static boolean isAnnotationPresent(Field field, Class<? extends Annotation> annotation) {
        if (field.isAnnotationPresent(annotation)) {
            return true;
        }
        //进行递归查询，处理组合注解
        for (Annotation ann : filterMetaAnnotation(field.getDeclaredAnnotations())) {
            Class<? extends Annotation> aClass = ann.annotationType();
            if (isAnnotationPresent(aClass, annotation)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 过滤元注解
     *
     * @param annotations 注解
     * @return 过滤后的注解
     */
    private static List<Annotation> filterMetaAnnotation(Annotation[] annotations) {
        return Arrays.stream(annotations).filter(annotation1 -> {
            Class<? extends Annotation> aClass = annotation1.annotationType();
            return !aClass.equals(Documented.class) && !aClass.equals(Inherited.class) && !aClass.equals(Native.class) && !aClass.equals(Repeatable.class) && !aClass.equals(Retention.class) && !aClass.equals(Target.class);
        }).collect(Collectors.toList());
    }
}
